﻿//Author:Michal Sporna
//License: https://operationsneakpeek.codeplex.com/license

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using System.IO;
using System.Reflection;
using Microsoft.Xna.Framework.Content;
using System.Xml.Linq;


namespace Levels
{
    public static class LevelManager
    {
        #region enum
       

        #endregion

        #region properties
        //list of available maps
        public static List<Map> AvailableMaps;
        //current map
        public static Map CurrentMap;

        #endregion

  
        #region private

        /// <summary>
        /// Determine current map cell based on avatar's position and CurrentMapCell
        /// </summary>
        //private static void _DetermineCurrentMapCell()
        //{


        //    try
        //    {
        //        if (Util.Cache.Avatar != null)
        //        {


        //            foreach (Portal p in CurrentMap.CurrentMapCell.Portals)
        //            {
        //                if ((Util.Cache.Avatar.CurrentPosition.X > p.X && p.X > -1) || (Util.Cache.Avatar.CurrentPosition.Y > p.Y && p.Y > -1))
        //                {
        //                    CurrentMap.CurrentMapCell = GetMapCellByName(p.NextCell);
        //                    //set avatar's position in the new cell
        //                    Util.Cache.Avatar.CurrentPosition = new Vector2(p.AvatarPosXNextCell, p.AvatarPosYNextCell);
        //                    Util.Cache.Avatar.FuturePosition = Util.Cache.Avatar.CurrentPosition;

        //                    //clear list of NPCs for current cell
        //                    CurrentMap.CurrentMapCell.NPCs = new List<Characters.NPC>();
        //                    //reset npcs
        //                    _LoadNPCsOfMapCell();


        //                    break;
        //                }
        //            }
        //        }



        //    }
        //    catch (Exception ex)
        //    {
        //        Util.ErrorLogging.LogError(ex);
        //        return;
        //    }
        //}


        /// <summary>
        /// Load NPCs to the current map cell
        /// </summary>
        private static void _LoadNPCsOfMapCell()
        {
            //declare
            Characters.NPC newNpc = null;
            Util.Classes.Event eventHelper;
            Util.Classes.EventParameter eventParHelper;

            try
            {
                //if npcs are set for this mapCell, then return
                if (CurrentMap.CurrentMapCell.NPCsSet)
                {
                   //this is not used anymore, npcSet is always false but not tested what happens if this line of code is removed

                    return;
                }

                foreach (Characters.NPC npc in Levels.LevelManager.CurrentMap.NPCs)
                {
                    if (npc == null)
                    {
                        continue;
                    }

                    //find npc in current map cell
                    foreach (Levels.npcPlacement npcPlacement in World.WorldManager.WorldConfig.NpcPlacement)
                    {
                        if (npcPlacement == null)
                        {
                            continue;
                        }

                        if (npcPlacement.MapID==Levels.LevelManager.CurrentMap.Name&&npcPlacement.MapCell == Levels.LevelManager.CurrentMap.CurrentMapCell.ID && npcPlacement.ID == npc.ID )
                        {
                            //create as many instances of NPCs as in config
                            for (int i = 0; i < npcPlacement.Number; i++)
                            {
                                //new NPC instance
                                newNpc = new Characters.NPC();
                                #region inherit most of the attributes from npc (from npcs of the map)
                                newNpc.ID = npc.ID;
                                newNpc.NPCType = npc.NPCType;
                                newNpc.Textures = npc.Textures;
                                newNpc.Width = npc.Width;
                                newNpc.Height = npc.Height;
                                newNpc.Step = npc.Step;
                                //newNpc.PartIDs = npc.PartIDs;
                                newNpc.Map = npc.Map;
                                newNpc.Events = npc.Events;
                                newNpc.Strength = npc.Strength;
                                newNpc.Perception = npc.Perception;
                                newNpc.Luck = npc.Luck;
                                newNpc.IQ = npc.IQ;
                                newNpc.SpecialAbilityID = npc.SpecialAbilityID;
                                newNpc.Health = npc.Health;

                                //increment unique ID
                                newNpc.UniqueID = i;
                                //set move patterns
                                newNpc.MovePatterns = LevelManager.CurrentMap.CurrentMapCell.GetMovePatternsByNPCUniqueID(newNpc.UniqueID+1, newNpc.ID);


                                //events
                                //newNpc.Events = npc.Events;

                                //new instance
                                newNpc.Events = new List<Util.Classes.Event>();
                                

                                //copy events from mather class
                                for(int eCt=0;eCt<npc.Events.Count;eCt++)
                                {
                                   
                                    //properties
                                    //new instance of event
                                    eventHelper = new Util.Classes.Event();
                                    eventHelper.EventType= npc.Events[eCt].EventType;
                                    eventHelper.Method = npc.Events[eCt].Method;
                                   
                                    newNpc.Events.Add(eventHelper);
                                    

                                    //parameters
                                    for (int pCt = 0; pCt < npc.Events[eCt].Parameters.Count; pCt++)
                                    {
                                        if (newNpc.Events[eCt].Parameters == null)
                                        {
                                            newNpc.Events[eCt].Parameters = new List<Util.Classes.EventParameter>();
                                        }

                                        eventParHelper = new Util.Classes.EventParameter();
                                        eventParHelper.Parameter = npc.Events[eCt].Parameters[pCt].Parameter;
                                        eventParHelper.ParameterString = npc.Events[eCt].Parameters[pCt].ParameterString;

                                        newNpc.Events[eCt].Parameters.Add(eventParHelper);
                                    }


                                }
                                
                                //if event has "this" paramter, then replace it with new npc instance
                                foreach (Util.Classes.Event e in newNpc.Events)
                                {
                                    foreach (Util.Classes.EventParameter param in e.Parameters)
                                    {
                                        if (param.ParameterString == "this")
                                        {
                                            //overwrite with new npc instance
                                            param.Parameter = newNpc;
                                            break;
                                        }
                                    }
                                }
                                #endregion

                              
                                //set start attributes
                                newNpc.MovePatternCt = 0;
                                newNpc.CurrentPosX = newNpc.MovePatterns[newNpc.MovePatternCt].StartX;
                                newNpc.CurrentPosY = newNpc.MovePatterns[newNpc.MovePatternCt].StartY;
                        
                                //add new npc to the list of current map cell's npcs
                                if (CurrentMap.CurrentMapCell.NPCs != null)
                                {
                                    CurrentMap.CurrentMapCell.NPCs.Add(newNpc);
                                }
                                else
                                {
                                    CurrentMap.CurrentMapCell.NPCs = new List<Characters.NPC>();
                                    CurrentMap.CurrentMapCell.NPCs.Add(newNpc);

                                    CurrentMap.CurrentMapCell.NPCsSet = true;
                                }
                            }

                        }
                    }

                }


            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }
       

        #endregion

        #region public
        public static int npcCounter;


        #endregion

        #region methods

        #region actions-events

        /// <summary>
        /// NPC calls backup
        /// and they surround the avatar
        /// and then arrest him or kill him
        /// </summary>
        public static void CallBackup(Characters.NPC NPCWhichSpottedAvatar)
        {
            try
            {
                //Util.Cache.Avatar.CanMove = false;

                //draw backup NPCs
                //3 new NPCs

                ///determine direction where npc is
                ///reinforments will come from other directions
                switch (NPCWhichSpottedAvatar.MovePatterns[NPCWhichSpottedAvatar.MovePatternCt].MoveDirection)
                {
                    case Util.Helpers.PublicEnums.NPCMoveDirection.right:
                        {





                            break;
                        }
                }




            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }


        /// <summary>
        /// nPC kills the avatar
        /// </summary>
        public static void KillAvatar(Characters.NPC NPC)
        {
            try
            {
                //Util.Cache.Avatar.CanMove = false;

                Util.Cache.Avatar.SetPreviousState();

                //make killing animation
                NPC.CurrentState = Util.Helpers.PublicEnums.NPCState.Attacking;
                





            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }


        }

        #endregion

       

        /// <summary>
        /// Get map cell by ID
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static MapCell GetMapCellByName(string name)
        {
            try
            {
                foreach (MapCell mc in CurrentMap.MapCells)
                {
                    if (mc.ID.ToLower() == name.ToLower())
                    {
                        return mc;
                    }
                }


                return null;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }
        }

        /// <summary>
        /// Get map info from
        /// game config by id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static MapInfo GetMapInfoByID(string id)
        {
            try
            {
                foreach (MapInfo mi in World.WorldManager.WorldConfig.Maps)
                {
                    if (mi.ID.ToLower() ==id.ToLower())
                    {
                        return mi;
                    }
                }


                return null;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }
        }

        #region Get Obstacle data
        /// <summary>
        /// Get obstacle by its ID (Name)
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Util.Classes.Obstacle GetObstacleByName(string name)
        {
            try
            {

                foreach (Util.Classes.Obstacle Obstacle in CurrentMap.AvailableObstacles)
                {
                    if (Obstacle.ID.ToLower() == name.ToLower())
                    {
                        return Obstacle;
                    }

                }

                return null;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }


        }


        /// <summary>
        /// Get obstacle to draw by related obstacle's ID (Name)
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Util.Classes.ObstacleToDraw GetObstacleToDrawByName(string name)
        {
            try
            {

                foreach (Util.Classes.ObstacleToDraw ObstacleToDraw in CurrentMap.CurrentMapCell.Obstacles)
                {
                    if (ObstacleToDraw.ObstacleID.ToLower() == name.ToLower())
                    {
                        return ObstacleToDraw;
                    }

                }

                return null;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }


        }

        /// <summary>
        /// Get obstacle to draw by position
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Util.Classes.ObstacleToDraw GetObstacleToDrawByPosition(Vector2 pos)
        {
            try
            {

                foreach (Util.Classes.ObstacleToDraw ObstacleToDraw in CurrentMap.CurrentMapCell.Obstacles)
                {
                    if (ObstacleToDraw.Position==pos)
                    {
                        return ObstacleToDraw;
                    }

                }

                return null;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }


        }


        #endregion

        #region Get Item data

        /// <summary>
        /// Get item by name/ID
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Util.Classes.Item GetItemByName(string name)
        {
            try
            {

                for (int i = 0; i < CurrentMap.AvailableItems.Count;i++)
                {
                    if (CurrentMap.AvailableItems[i].Name.ToLower() == name.ToLower())
                    {
                        return CurrentMap.AvailableItems[i];
                    }

                }

                return null;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }


        }


        /// <summary>
        /// Get item to draw by related item's ID (Name)
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Util.Classes.ItemToDraw GetItemToDrawByName(string name)
        {
            try
            {

                foreach (Util.Classes.ItemToDraw ItemToDraw in CurrentMap.CurrentMapCell.CollectableItems)
                {
                    if (ItemToDraw.ItemID.ToLower() == name.ToLower())
                    {
                        return ItemToDraw;
                    }

                }

                return null;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }


        }

        #endregion

        #region GetBombData

        /// <summary>
        /// Get item by name/ID
        /// </summary>
        /// <param name="name"></param>GetBombByName
        /// <returns></returns>
        public static Util.Classes.Bomb GetBombByName(string name)
        {
            try
            {

                foreach (Util.Classes.Bomb bomb in CurrentMap.AvailableBombs)
                {
                    if (bomb.Name.ToLower() == name.ToLower())
                    {
                        return bomb;
                    }

                }

                return null;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }


        }

        /// <summary>
        /// Get shieldType
        /// from obstacle by obstacleID
        /// </summary>
        /// <param name="obstalceID"></param>
        /// <returns></returns>
        public static Util.Helpers.PublicEnums.ShieldType GetObstacleIsShieldType(string obstalceID)
        {
            try
            {
                for (int i = 0; i < CurrentMap.AvailableObstacles.Count; i++)
                {
                    if (CurrentMap.AvailableObstacles[i].ID == obstalceID)
                    {
                        return CurrentMap.AvailableObstacles[i].ShieldType;
                    }
                }


                return Util.Helpers.PublicEnums.ShieldType.None;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return Util.Helpers.PublicEnums.ShieldType.None;
            }
        }

       


        /// <summary>
        /// Get item to draw by related item's ID (Name)
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Util.Classes.BombToDraw GetBombToDrawByName(string name)
        {
            try
            {

                foreach (Util.Classes.BombToDraw btd in CurrentMap.CurrentMapCell.Bombs)
                {
                    if (btd.BombID.ToLower() == name.ToLower())
                    {
                        return btd;
                    }

                }

                return null;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }


        }


        #endregion

        #region init maps

        #region NEW, when level choosing menu is available already

        /// <summary>
       /// Load selected map
       /// </summary>
        public static void LoadMap()
        {
            //declare
            Stream xmlStream = null;
          

            try
            {
              
                #region map config file
                foreach (Levels.MapInfo mInfo in World.WorldManager.WorldConfig.Maps)
                {

                    //load this map only if it's been chosen by user from menu
                    if (!mInfo.ChosenMap)
                    {
                        break;
                    }


                    //load xml file of the map
                    xmlStream = TitleContainer.OpenStream(mInfo.Path);
                    //load los albatros map
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    CurrentMap = Util.Helpers.XMLParser.LoadMap();

                    //if read map is not null, add to the list
                    if (CurrentMap != null)
                    {
                        CurrentMap.IsCurrentMap = true; //no sense but let it be for now
                        CurrentMap.WildPasswordGuesses = CurrentMap.DefaultWildPassGuessesNumber;//this number will be altered in LoadWordSTate() if necessary

                        //load map data from storage(if saved)
                        World.StorageManager.LoadWorldInfo();
                        World.StorageManager.LoadAwardedStarsStateForTheMap(mInfo.ID);
                        World.StorageManager.LoadWordState(mInfo.ID);
                        World.StorageManager.LoadBombState(mInfo.ID);

                        //get points from map info
                        CurrentMap.Points = mInfo.Points;

                       


                        return;
                     
                    }
                }

                //cleanup
                World.WorldManager.WorldConfig.Maps = null;
                #endregion

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        /// <summary>
        /// Load Map cells of current map
        /// </summary>
        public static void LoadMapCells()
        {
             //declare
            Stream xmlStream = null;
            MapCell readMapCell;

            try
            {
                #region parts
                //load xmls of parts
                for (int i = 0; i < CurrentMap.MapCells.Count; i++)
                {
                    xmlStream = TitleContainer.OpenStream("Content\\Maps\\"+CurrentMap.Name+"\\Parts\\" + CurrentMap.MapCells[i].ID + ".xml");
                    //load part
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readMapCell = Util.Helpers.XMLParser.LoadMapCell();

                    //if read map is not null, add to the list
                    if (readMapCell != null)
                    {

                        //#region LOAD Bombs after effect
                        //readMapCell.BombsAfterEffect = new List<Util.Classes.BombAfterEffect>();
                        ////load
                        //if (readMapCell.BombsAfterEffect.Count > 0)
                        //{
                        //    foreach (Util.Classes.BombAfterEffect baf in readMapCell.BombsAfterEffect)
                        //    {
                        //        for (int i1 = 0; i < readMapCell.Bombs.Count; i1++)
                        //        {
                        //            if (readMapCell.Bombs[i1].Position.X == baf.BombPos[0] && readMapCell.Bombs[i1].Position.Y == baf.BombPos[1])
                        //            {
                        //                readMapCell.Bombs[i1].Found = baf.Found;
                        //                readMapCell.Bombs[i1].Defused = baf.Defused;
                        //            }
                        //        }
                        //    }
                        //}
                        

                        //#endregion

                        //assign readMapCell to currently processed map cell, 
                        //as this instance has only ID so far. Overwrite, to assign all properties
                        CurrentMap.MapCells[i] = readMapCell;

                       
                    }
                }
                #endregion
            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        /// <summary>
        /// load obstacles
        /// </summary>
        public static void LoadObstacle(string obstacleID)
        {
            //declare
            Stream xmlStream = null;
            Util.Classes.Obstacle readObstacle;

            try
            {
                #region obstacles
                
                    xmlStream = TitleContainer.OpenStream("Content\\Obstacles\\XML\\" + obstacleID + ".xml");
                    //load part
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readObstacle = Util.Helpers.XMLParser.LoadObstacle();

                    //if read obstacle is not null, set the rest of properties
                    //that were read from the file
                    if (readObstacle != null)
                    {
                        

                        //add to the list of obstacles
                        CurrentMap.AvailableObstacles.Add(readObstacle);

                        //find obstacle to draw and assign dimensions to the obstalces
                        for (int i = 0; i < CurrentMap.CurrentMapCell.Obstacles.Count; i++)
                        {
                            if (CurrentMap.CurrentMapCell.Obstacles[i].ObstacleID == readObstacle.ID)
                            {
                                CurrentMap.CurrentMapCell.Obstacles[i].Dimensions = new int[] { readObstacle.Width, readObstacle.Height };
                                CurrentMap.CurrentMapCell.Obstacles[i].DimensionsSet = true;
                                CurrentMap.CurrentMapCell.Obstacles[i].Walkable = readObstacle.Walkable;
                                CurrentMap.CurrentMapCell.Obstacles[i].Type = readObstacle.Type;
                                CurrentMap.CurrentMapCell.Obstacles[i].IsWater = readObstacle.IsWater;
                                CurrentMap.CurrentMapCell.Obstacles[i].TextureName = readObstacle.TextureName;
                                
                            }
                        }

                        //readMap.AvailableObstacles[i].TextureName = readObstacle.TextureName;
                        //readMap.AvailableObstacles[i].Width = readObstacle.Width;
                        //readMap.AvailableObstacles[i].Height = readObstacle.Height;
                        //readMap.AvailableObstacles[i].Type = readObstacle.Type;
                        //readMap.AvailableObstacles[i].HarmMultiplier = readObstacle.HarmMultiplier;
                        //readMap.AvailableObstacles[i].OffsetUp = readObstacle.OffsetUp;
                        //readMap.AvailableObstacles[i].OffsetDown = readObstacle.OffsetDown;
                        //readMap.AvailableObstacles[i].OffsetRight = readObstacle.OffsetRight;
                        //readMap.AvailableObstacles[i].OffsetLeft = readObstacle.OffsetLeft;
                        //readMap.AvailableObstacles[i].IsWater = readObstacle.IsWater;
                        //readMap.AvailableObstacles[i].Walkable = readObstacle.Walkable;
                        //readMap.AvailableObstacles[i].ItemsInteracting = readObstacle.ItemsInteracting;
                        //readMap.AvailableObstacles[i].Events = readObstacle.Events;
                        //readMap.AvailableObstacles[i].ShieldType = readObstacle.ShieldType;
                        //readMap.AvailableObstacles[i].DynamicChangeTime = readObstacle.DynamicChangeTime;
                    }

                //cleaunp
                    readObstacle = null;
                


                #endregion

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }


        }

        /// <summary>
        /// load invisible,
        /// non walkable
        /// obstacle that blocks avatar from going outside the map cell boundries
        /// </summary>
        public static void LoadEndOfMapObstacles()
        {
            try
            {

                ////add invisible, non walkable obstacle
                //Util.Classes.Obstacle endOfMapObstacle = new Util.Classes.Obstacle();
                //endOfMapObstacle.ID = "EndOfMapObstacleUp";
                //endOfMapObstacle.Walkable = false;
                //endOfMapObstacle.Type = Util.Helpers.PublicEnums.ObstacleType.StaticNoHarm;
                //endOfMapObstacle.Width = Util.Cache.GraphicsDevice.Viewport.Width;
                //endOfMapObstacle.Height = 1;
                //endOfMapObstacle.TextureName = "redRect";
                ////add
                //CurrentMap.AvailableObstacles.Add(endOfMapObstacle);


                //endOfMapObstacle = new Util.Classes.Obstacle();
                //endOfMapObstacle.ID = "EndOfMapObstacleDown";
                //endOfMapObstacle.Walkable = false;
                //endOfMapObstacle.Type = Util.Helpers.PublicEnums.ObstacleType.StaticNoHarm;
                //endOfMapObstacle.Width = Util.Cache.GraphicsDevice.Viewport.Width;
                //endOfMapObstacle.Height = 1;
                //endOfMapObstacle.TextureName = "redRect";
                ////add
                //CurrentMap.AvailableObstacles.Add(endOfMapObstacle);

                //endOfMapObstacle = new Util.Classes.Obstacle();
                //endOfMapObstacle.ID = "EndOfMapObstacleRight";
                //endOfMapObstacle.Walkable = false;
                //endOfMapObstacle.Type = Util.Helpers.PublicEnums.ObstacleType.StaticNoHarm;
                //endOfMapObstacle.Width = 1;
                //endOfMapObstacle.Height = Util.Cache.GraphicsDevice.Viewport.Height;
                //endOfMapObstacle.TextureName = "redRect";
                ////add
                //CurrentMap.AvailableObstacles.Add(endOfMapObstacle);

                //endOfMapObstacle = new Util.Classes.Obstacle();
                //endOfMapObstacle.ID = "EndOfMapObstacleLeft";
                //endOfMapObstacle.Walkable = false;
                //endOfMapObstacle.Type = Util.Helpers.PublicEnums.ObstacleType.StaticNoHarm;
                //endOfMapObstacle.Width = 1;
                //endOfMapObstacle.Height = Util.Cache.GraphicsDevice.Viewport.Height;
                //endOfMapObstacle.TextureName = "redRect";
                ////add
                //CurrentMap.AvailableObstacles.Add(endOfMapObstacle);
            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        /// <summary>
        /// Load powerups
        /// </summary>
        public static void LoadPowerups()
        {
            try
            {
                World.WorldManager.Powerups = new List<Util.Classes.Powerup>();
                for (int i = 0; i < 5; i++)
                {

                    Util.Classes.Powerup p = new Util.Classes.Powerup();
                    p.Rect = new Rectangle(0, 0, 0, 0);
                    World.WorldManager.Powerups.Add(p);
                }

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        /// <summary>
        /// load item
        /// </summary>
        /// <param name="itemID"></param>
        public static void LoadItem(string itemID)
        {
            //declare
            Stream xmlStream = null;
            Util.Classes.Item readItem;

            try
            {

                #region items

               

                    xmlStream = TitleContainer.OpenStream("Content\\Items\\XML\\" + itemID + ".xml");
                    //load part
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readItem = Util.Helpers.XMLParser.LoadItem();

                    //if read item is not null, set the rest of properties
                    //that were read from the file
                    if (readItem != null)
                    {
                        //add to collection of items
                        CurrentMap.AvailableItems.Add(readItem);

                        //get dimensions of the item from item to item to draw
                        for (int i = 0; i < CurrentMap.CurrentMapCell.CollectableItems.Count; i++)
                        {
                            if (CurrentMap.CurrentMapCell.CollectableItems[i].ItemID == readItem.Name)
                            {
                                CurrentMap.CurrentMapCell.CollectableItems[i].TextureName = readItem.TextureName;
                                CurrentMap.CurrentMapCell.CollectableItems[i].Dimensions = new int[] { (int)readItem.Width, (int)readItem.Height };
                              
                            }
                        }

                    }

                    //cleanup
                    readItem = null;

                



                #endregion


            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        /// <summary>
        /// load bomb
        /// </summary>
        /// <param name="bombID"></param>
        public static void LoadBomb(string bombID)
        {
            //declare
            Stream xmlStream = null;
            Util.Classes.Bomb readBomb;

            try
            {
                #region bombs

                   
                    xmlStream = TitleContainer.OpenStream("Content\\Bombs\\XML\\" + bombID + ".xml");
                    //load bomb
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readBomb = Util.Helpers.XMLParser.LoadBomb();

                    //if read item is not null, set the rest of properties
                    //that were read from the file
                    if (readBomb != null)
                    {
                        //see if bombs after effect are loaded, and if yes, mark the bomb
                        

                        //add to the collection of bombs
                        CurrentMap.AvailableBombs.Add(readBomb);

                        //load bomb
                        for (int i = 0; i < CurrentMap.CurrentMapCell.Bombs.Count; i++)
                        {
                            if (CurrentMap.CurrentMapCell.Bombs[i].BombID == readBomb.Name)
                            {
                                CurrentMap.CurrentMapCell.Bombs[i].Dimensions = new int[] { (int)readBomb.Width, (int)readBomb.Height };
                                CurrentMap.CurrentMapCell.Bombs[i].DimensionsSet = true;
                            }
                        }
                        
                    }

                    //cleanup
                    readBomb = null;
                





                #endregion

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }

        }

        /// <summary>
        /// Load NPCs
        /// </summary>
        public static void LoadNPCs()
        {
            //declare
            Stream xmlStream = null;

            try
            {
                //reset fields
                npcCounter = 0;

                if (CurrentMap.NPCs == null || CurrentMap.NPCs.Count==0)
                {
                    #region load npcs

                    //load npcs
                    if (CurrentMap.NPCInfo != null)
                    {
                        foreach (Levels.NPCInfo npcInfo in CurrentMap.NPCInfo)
                        {

                            xmlStream = TitleContainer.OpenStream(npcInfo.Path);
                            Util.Helpers.XMLParser.LoadXML(xmlStream);
                            CurrentMap.NPCs.Add(Util.Helpers.XMLParser.LoadNPC());
                        }

                        //cleanup
                        //CurrentMap.NPCInfo = null;
                    }
                    #endregion


                }

                    //load npcs to the current map cell 
                    _LoadNPCsOfMapCell();
                
               
            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        #endregion




        /// <summary>
        /// OBSOLETE
        /// NOT BEING USED ANYMORE
        /// </summary>
        public static void InitMaps()
        {
            //declare
            Stream xmlStream = null;
            Map readMap = null;
            MapCell readMapCell;
            Util.Classes.Obstacle readObstacle;
            Util.Classes.Item readItem;
            Util.Classes.Bomb readBomb;

            try
            {
                //reset fields
                npcCounter = 0;


                //if a list of available maps is empty, create
                if (AvailableMaps == null)
                {
                    AvailableMaps = new List<Map>();
                }

                #region load maps

                #region map config file
                foreach (Levels.MapInfo mInfo in World.WorldManager.WorldConfig.Maps)
                {
                    

                    //load xml file of the map
                    xmlStream = TitleContainer.OpenStream(mInfo.Path);
                    //load los albatros map
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readMap = Util.Helpers.XMLParser.LoadMap();

                    //if read map is not null, add to the list
                    if (readMap != null)
                    {
                        AvailableMaps.Add(readMap);
                    }
                }

                //cleanup
                //World.WorldManager.WorldConfig.Maps = null;
                #endregion

                #region parts
                //load xmls of parts
                for (int i = 0; i < readMap.MapCells.Count; i++)
                {
                    //read parts only of the current map
                    if (!readMap.IsCurrentMap)
                    {
                        break;
                    }

                    xmlStream = TitleContainer.OpenStream("Content\\Maps\\map_LosAlbatros\\Parts\\" + readMap.MapCells[i].ID + ".xml");
                    //load part
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readMapCell = Util.Helpers.XMLParser.LoadMapCell();

                    //if read map is not null, add to the list
                    if (readMapCell != null)
                    {
                        readMap.MapCells[i] = readMapCell;

                        //if readMapCell has the same ID as current map cell, re-assign
                        if (readMapCell.ID == CurrentMap.CurrentMapCell.ID)
                        {
                            //first map cell loaded is the first map cell
                            CurrentMap.CurrentMapCell = readMapCell;

                        }
                    }
                }
                #endregion

                #region obstacles
                for (int i = 0; i < readMap.AvailableObstacles.Count; i++)
                {
                    //read parts only of the current map
                    if (!readMap.IsCurrentMap)
                    {
                        break;
                    }

                    xmlStream = TitleContainer.OpenStream("Content\\Obstacles\\XML\\" + readMap.AvailableObstacles[i].ID + ".xml");
                    //load part
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readObstacle = Util.Helpers.XMLParser.LoadObstacle();

                    //if read obstacle is not null, set the rest of properties
                    //that were read from the file
                    if (readObstacle != null)
                    {
                        readMap.AvailableObstacles[i].TextureName = readObstacle.TextureName;
                        readMap.AvailableObstacles[i].Width = readObstacle.Width;
                        readMap.AvailableObstacles[i].Height = readObstacle.Height;
                        readMap.AvailableObstacles[i].Type = readObstacle.Type;
                        readMap.AvailableObstacles[i].HarmMultiplier = readObstacle.HarmMultiplier;
                        readMap.AvailableObstacles[i].OffsetUp = readObstacle.OffsetUp;
                        readMap.AvailableObstacles[i].OffsetDown = readObstacle.OffsetDown;
                        readMap.AvailableObstacles[i].OffsetRight = readObstacle.OffsetRight;
                        readMap.AvailableObstacles[i].OffsetLeft = readObstacle.OffsetLeft;
                        readMap.AvailableObstacles[i].IsWater = readObstacle.IsWater;
                        readMap.AvailableObstacles[i].Walkable = readObstacle.Walkable;
                        readMap.AvailableObstacles[i].ItemsInteracting = readObstacle.ItemsInteracting;
                        readMap.AvailableObstacles[i].Events = readObstacle.Events;
                        readMap.AvailableObstacles[i].ShieldType = readObstacle.ShieldType;
                        readMap.AvailableObstacles[i].DynamicChangeTime = readObstacle.DynamicChangeTime;
                    }


                }


                #endregion

                //prepare obstacles to draw of state2
                CurrentMap.CurrentMapCell.PrepareState2OfObstacles();


                #region items

                for (int i = 0; i < readMap.AvailableItems.Count; i++)
                {
                    //read parts only of the current map
                    if (!readMap.IsCurrentMap)
                    {
                        break;
                    }

                    xmlStream = TitleContainer.OpenStream("Content\\Items\\XML\\" + readMap.AvailableItems[i].Name + ".xml");
                    //load part
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readItem = Util.Helpers.XMLParser.LoadItem();

                    //if read item is not null, set the rest of properties
                    //that were read from the file
                    if (readItem != null)
                    {
                        readMap.AvailableItems[i].TextureName = readItem.TextureName;
                        readMap.AvailableItems[i].Width = readItem.Width;
                        readMap.AvailableItems[i].Height = readItem.Height;
                        readMap.AvailableItems[i].Event = readItem.Event;
                        readMap.AvailableItems[i].Offset = readItem.Offset;
                        readMap.AvailableItems[i].Efficiency = readItem.Efficiency;
                    }

                    //cleanup
                    readItem = null;

                }



                #endregion

                #region bombs

                for (int i = 0; i < readMap.AvailableBombs.Count; i++)
                {
                    //read parts only of the current map
                    if (!readMap.IsCurrentMap)
                    {
                        break;
                    }

                    xmlStream = TitleContainer.OpenStream("Content\\Bombs\\XML\\" + readMap.AvailableBombs[i].Name + ".xml");
                    //load part
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readBomb = Util.Helpers.XMLParser.LoadBomb();

                    //if read item is not null, set the rest of properties
                    //that were read from the file
                    if (readBomb != null)
                    {
                        readMap.AvailableBombs[i].Width = readBomb.Width;
                        readMap.AvailableBombs[i].Height = readBomb.Height;
                        readMap.AvailableBombs[i].Texture = readBomb.Texture;
                        readMap.AvailableBombs[i].ExplosionType = readBomb.ExplosionType;
                        readMap.AvailableBombs[i].BonusTime = readBomb.BonusTime;
                        readMap.AvailableBombs[i].Events = readBomb.Events;
                        readMap.AvailableBombs[i].Shuffle = readBomb.Shuffle;
                        readMap.AvailableBombs[i].Wires = readBomb.Wires;
                        readMap.AvailableBombs[i].Difficulty = readBomb.Difficulty;
                        readMap.AvailableBombs[i].DefusingWireGracePeriod = readBomb.DefusingWireGracePeriod;
                        readMap.AvailableBombs[i].TimeToSubtractOnBombFailed = readBomb.TimeToSubtractOnBombFailed;
                    }

                    //cleanup
                    readBomb = null;
                }


              


                #endregion

                #region load npcs

                //load npcs
                foreach (Levels.NPCInfo npcInfo in readMap.NPCInfo)
                {
                    xmlStream = TitleContainer.OpenStream(npcInfo.Path);
                    Util.Helpers.XMLParser.LoadXML(xmlStream);
                    readMap.NPCs.Add(Util.Helpers.XMLParser.LoadNPC());
                }

                //cleanup
                readMap.NPCInfo = null;

                #endregion


                //load npcs to the current map cell (first map cell)
                _LoadNPCsOfMapCell();

                //TEMPORARY
                //powerups
                World.WorldManager.Powerups = new List<Util.Classes.Powerup>();
                for (int i = 0; i < 5; i++)
                {
                    
                    Util.Classes.Powerup p = new Util.Classes.Powerup();
                    p.Rect = new Rectangle(0, 0, 0, 0);
                    World.WorldManager.Powerups.Add(p);
                }

                #endregion


            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
            finally
            {
                //dispose of everything
                if (xmlStream != null)
                {
                    xmlStream.Close();
                    xmlStream.Dispose();
                }
                //finish working with the xml
                Util.Helpers.XMLParser.FinishWorkingWithXML();
                World.WorldManager.EverythingLoaded = true;
            }

        }


        /// <summary>
        /// Set current map cell
        /// </summary>
        public static void SetCurrentMapCell(Portal touchedPortal)
        {
            try
            {
                for (int i1 = 0; i1 < Levels.LevelManager.CurrentMap.MapCells.Count; i1++)
                {
                    if (Levels.LevelManager.CurrentMap.MapCells[i1].ID == touchedPortal.NextCell)
                    {
                        //assign as current map cell
                        Levels.LevelManager.CurrentMap.CurrentMapCell = Levels.LevelManager.CurrentMap.MapCells[i1];
                        break;
                    }
                }

                //set avatar's position according to map cell's avatar placement
                Util.Cache.Avatar.CurrentPosition = new Vector2(touchedPortal.AvatarPosInNextMapCell[0], touchedPortal.AvatarPosInNextMapCell[1]);
                Util.Cache.Avatar.CurrentState = Levels.LevelManager.CurrentMap.CurrentMapCell.AvatarPlacement[0].AvatarState;


                //LoadMap();

                CurrentMap.CurrentMapCell.NPCsSet = false;
                World.WorldManager.IsHeatActive = false;//reset heat
                CurrentMap.CurrentMapCell.NPCs = null;

                //load data
                World.WorldManager.LoadGameData(Util.Cache.Screen.Game);

                //load content for a specified screen(new screen)
                World.WorldManager.LoadContent(Util.Cache.Screen.Game);

                World.WorldManager.Nodes = null;
                World.PathFinding.InitNodes();

                ////randomly set uncovered letters on the map cell
                //CurrentMap.ChosenSecretWord.PositionLetters();
               

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        #endregion




        #region DRAW MAP

        /// <summary>
        /// Draw the map
        /// </summary>
        /// <param name="avatarPosition"></param>
        public static void DrawMap()
        {
            try
            {
                //first, determine current map cell
                //_DetermineCurrentMapCell();
                //draw current map cell
                CurrentMap.CurrentMapCell.DrawCell();


                //drawing current map...
                #region draw textures
                //foreach (Util.Classes.TextureToDraw ttd in CurrentMap.CurrentMapCell.TexturesToDraw)
                //{
                //    Util.Cache.Draw(Util.Cache.GetTexture(ttd.Texture).Text2D, new Rectangle(ttd.X, ttd.Y, ttd.Width, ttd.Height), Color.White);
                //}

                



                #endregion


            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }


        }

        #endregion


        #endregion




    }
}
